﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

// Courtesy of the camera tutorial at www.3dgameprogramming.net

namespace nu_portal
{
    public class Camera : DrawableGameComponent
    {
        private static Camera activeCamera = null;
        private static float SPD = 0.9f;
        private static float MVSPD = 100f;

        public Matrix projection = Matrix.Identity;
        public Matrix view = Matrix.Identity;

        public Vector3 pos = Vector3.Zero;
        public Vector3 angle = Vector3.Zero;

        public Camera(Game game) : base(game)
        {
            if (activeCamera == null)
                activeCamera = this;
        }

        public override void Initialize()
        {
            Mouse.SetPosition(Game.Window.ClientBounds.Width / 2, Game.Window.ClientBounds.Height / 2);
            
            base.Initialize();
        }

        protected override void LoadGraphicsContent()
        {
            float aspect = (float)GraphicsDevice.Viewport.Width / (float)GraphicsDevice.Viewport.Height;
            projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect, 0.1f, 100);

            base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
            float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
            KeyboardState ks = Keyboard.GetState();
            MouseState ms = Mouse.GetState();
            int centerX = Game.Window.ClientBounds.Width / 2;
            int centerY = Game.Window.ClientBounds.Height / 2;
            Mouse.SetPosition(centerX, centerY);

            angle.X += MathHelper.ToRadians((ms.Y - centerY) * SPD);
            angle.Y += MathHelper.ToRadians((ms.X - centerX) * SPD);

            Vector3 forwards = Vector3.Normalize(new Vector3((float)Math.Sin(-angle.Y), 
                                                             (float)Math.Sin(angle.X), 
                                                             (float)Math.Cos(-angle.Y)));
            Vector3 left = Vector3.Normalize(new Vector3((float)Math.Cos(angle.Y),
                                                         0f,
                                                         (float)Math.Sin(angle.Y)));

            if (ks.IsKeyDown(Keys.W))
                pos += forwards * MVSPD * elapsedTime;
            if (ks.IsKeyDown(Keys.S))
                pos -= forwards * MVSPD * elapsedTime;
            if (ks.IsKeyDown(Keys.A))
                pos += left * MVSPD * 0.9f * elapsedTime;
            if (ks.IsKeyDown(Keys.D))
                pos -= left * MVSPD * 0.9f * elapsedTime;

            if (ks.IsKeyDown(Keys.Up))
                pos += Vector3.Up * SPD * elapsedTime;
            if (ks.IsKeyDown(Keys.Down))
                pos += Vector3.Down * SPD * elapsedTime;

            view = Matrix.Identity;
            view *= Matrix.CreateTranslation(-pos);
            view *= Matrix.CreateRotationZ(angle.Z);
            view *= Matrix.CreateRotationY(angle.Y);
            view *= Matrix.CreateRotationX(angle.X);

            base.Update(gameTime);
        }
    }
}
